﻿using MobileDesigner.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using WebMatrix.WebData;
using PagedList;

namespace MobileDesigner.Controllers
{
    public class AdminController : Controller
    {
        private MobileDesignerContext db = new MobileDesignerContext();

        //
        // GET: /Admin/Accounts

        [Authorize(Roles = "Administrator")]
        public ViewResult Accounts(string sortOrder, string currentFilter, string searchString, int? page)
        {
            ViewBag.CurrentSort = sortOrder;
            ViewBag.EmailSortParm = String.IsNullOrEmpty(sortOrder) ? "Email desc" : "";
            ViewBag.NameSortParm = sortOrder == "Name" ? "Name desc" : "Name";

            if (Request.HttpMethod == "GET")
            {
                searchString = currentFilter;
            }
            else
            {
                page = 1;
            }
            ViewBag.CurrentFilter = searchString;

            var users = (from u in db.Users
                         select new AdminListUserModel
                         {
                             ID = u.ID,
                             Email = u.Email,
                             Name = u.LastName + " " + u.Name,
                             Phone = u.Phone,
                             SuperiorName = db.Users.FirstOrDefault(_u => _u.ID == u.SuperiorID).LastName + " " + db.Users.FirstOrDefault(_u => _u.ID == u.SuperiorID).Name
                         });

            if (!String.IsNullOrEmpty(searchString))
            {
                users = users.Where(u => u.Email.ToUpper().Contains(searchString.ToUpper())
                                       || u.Name.ToUpper().Contains(searchString.ToUpper()));
            }
            switch (sortOrder)
            {
                case "Name desc":
                    users = users.OrderByDescending(u => u.Name);
                    break;
                case "Email desc":
                    users = users.OrderByDescending(u => u.Email);
                    break;
                case "Name":
                    users = users.OrderBy(u => u.Name);
                    break;
                default:
                    users = users.OrderBy(u => u.Email);
                    break;
            }

            int pageSize = 10;
            int pageNumber = (page ?? 1);

            return View(users.ToPagedList(pageNumber, pageSize));
        }

        //
        // GET: /Admin/Create

        [Authorize(Roles = "Administrator")]
        public ActionResult Create()
        {
            ViewBag.Managers = GetManagers();
            return View();
        }

        //
        // POST: /Admin/Create

        [HttpPost]
        public ActionResult Create(AdminCreateUserModel newUser)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    if (!WebSecurity.UserExists(newUser.Email))
                    {
                        WebSecurity.CreateUserAndAccount(newUser.Email, newUser.Password, new { Phone = newUser.Phone, SuperiorID = newUser.SuperiorID, Name = newUser.Name, LastName = newUser.LastName });
                        if (!Roles.GetRolesForUser(newUser.Email).Contains(newUser.UserGroup))
                            Roles.AddUsersToRoles(new[] { newUser.Email }, new[] { newUser.UserGroup });
                    }
                    else
                    {
                        throw new DataException("Пользователь с таким электронным адресом уже существует");
                    }
                    return RedirectToAction("Accounts");
                }
            }
            catch (DataException e)
            {
                ModelState.AddModelError("", (e.Message != null) ? e.Message : "Unable to save changes. Try again, and if the problem persists see your system administrator.");
            }
            return View(newUser);
        }

        //
        // GET: /Admin/Edit/5

        [Authorize(Roles = "Administrator")]
        public ActionResult Edit(int id)
        {
            User user = db.Users.Find(id);
            ViewBag.Managers = GetManagers(user.SuperiorID.ToString());
            AdminEditUserModel userToEdit = new AdminEditUserModel { UserId = id, Email = user.Email, Phone = user.Phone, SuperiorID = user.SuperiorID, UserGroup = Roles.GetRolesForUser(user.Email).FirstOrDefault(), Name = user.Name, LastName = user.LastName };

            return View(userToEdit);
        }

        //
        // POST: /Admin/Edit/5

        [HttpPost]
        public ActionResult Edit(AdminEditUserModel userToEdit)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    User user = db.Users.Find(userToEdit.UserId);

                    bool isChanged = false;

                    if (user.Email != userToEdit.Email)
                    {
                        var found = from u in db.Users
                                    where u.Email == userToEdit.Email && u.ID != userToEdit.UserId
                                    select u;
                        if (found.FirstOrDefault() != null)
                            throw new DataException("There is a user with the same email.");

                        user.Email = userToEdit.Email;
                        isChanged = true;
                    }
                    if (user.Phone != userToEdit.Phone)
                    {
                        user.Phone = userToEdit.Phone;
                        isChanged = true;
                    }

                    if (user.SuperiorID != userToEdit.SuperiorID)
                    {
                        user.SuperiorID = userToEdit.SuperiorID;
                        isChanged = true;
                    }

                    if (isChanged) db.SaveChanges();

                    if (Roles.GetRolesForUser(user.Email).FirstOrDefault() != userToEdit.UserGroup)
                    {
                        Roles.RemoveUserFromRole(user.Email, Roles.GetRolesForUser(user.Email).FirstOrDefault());
                        Roles.AddUserToRole(user.Email, userToEdit.UserGroup);
                    }

                    return RedirectToAction("Accounts");
                }
            }
            catch (DataException e)
            {
                ModelState.AddModelError("", (e.Message != null) ? e.Message : "Unable to save changes. Try again, and if the problem persists see your system administrator.");
            }
            return View(userToEdit);
        }

        //
        // GET: /Admin/Delete/5

        [Authorize(Roles = "Administrator")]
        public ActionResult Delete(int id, bool? saveChangesError)
        {
            if (saveChangesError.GetValueOrDefault())
            {
                ViewBag.ErrorMessage = "Unable to save changes. Try again, and if the problem persists see your system administrator.";
            }
            User user = db.Users.Find(id);
            AdminEditUserModel userToDelete = new AdminEditUserModel { 
                UserId = id, 
                Email = user.Email, 
                Phone = user.Phone, 
                SuperiorID = user.SuperiorID, 
                Name = user.Name, 
                LastName = user.LastName, 
                UserGroup = Roles.GetRolesForUser(user.Email).FirstOrDefault() };
            return View(userToDelete);
        }


        //
        // POST: /Admin/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {
            try
            {
                User user = db.Users.Find(id);
                 if (Roles.GetRolesForUser(user.Email).Count() > 0)
                {
                    Roles.RemoveUserFromRoles(user.Email, Roles.GetRolesForUser(user.Email));
                }
                Membership.DeleteUser(user.Email, true);
            }
            catch (DataException e)
            {
                Response.Write(e.InnerException.Message);
            }
            return RedirectToAction("Accounts");
        }

        private SelectList GetManagers()
        {
            IList<SelectListItem> managers = new List<SelectListItem>();
            managers.Add(new SelectListItem { Selected = true, Text = "Нету сотрудника", Value = "0" });
            foreach (var item in db.Users)
            {
                if (!Roles.IsUserInRole(item.Email, "Client"))
                    managers.Add(new SelectListItem { Value = item.ID.ToString(), Text = item.LastName + " " + item.Name, Selected = false });
            }
            return new SelectList(managers, "Value", "Text");
        }

        private SelectList GetManagers(string selectedValue)
        {
            IList<SelectListItem> managers = new List<SelectListItem>();
            managers.Add(new SelectListItem { Selected = true, Text = "Нету сотрудника", Value = "0" });
            foreach (var item in db.Users)
            {
                if (!Roles.IsUserInRole(item.Email, "Client"))
                    managers.Add(new SelectListItem { Value = item.ID.ToString(), Text = item.LastName + " " + item.Name, Selected = false });
            }
            return new SelectList(managers, "Value", "Text", selectedValue);
        }
    }
}
